package org.yray.webtest.controller;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpRequest;
import org.springframework.http.MediaType;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import sun.misc.IOUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Objects;

@RestController
@Slf4j
@RequestMapping("download")
public class DownloadController {

    private String filePath="/data/";

    @GetMapping("/chunk")
    public void chunk(ServletRequest req, ServletResponse resp) {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        OutputStream os = null;
        String downfile = filePath+"offline.tar.gz";
        File zipFile = null;
        RandomAccessFile randomAccessFile=null;
        try {
            zipFile = new File(downfile);
            //动态根据业务创建文件
            if (zipFile.exists()) {
                long downloadStart = System.currentTimeMillis();
                randomAccessFile= new RandomAccessFile(zipFile,"r");
                response.reset();
                os = new BufferedOutputStream(response.getOutputStream());
                String userAgent = request.getHeader("USER-AGENT");
                String fileName = zipFile.getName();
                if (null != userAgent && -1 != userAgent.indexOf("MSIE")) {
                    fileName = URLEncoder.encode(fileName, "UTF8");
                } else if (null != userAgent && -1 != userAgent.indexOf("Mozilla")) {
                    fileName = new String(fileName.getBytes(
                            "utf-8"),
                            "ISO-8859-1");
                }
                response.setHeader("Accept-Ranges", "bytes");
                response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
                response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
                long pos = 0, fileSize = zipFile.length(), last = fileSize - 1;
                response.setHeader("ETag", zipFile.getName().concat(Objects.toString(fileSize)).concat("_").concat(Objects.toString(zipFile.lastModified())));
                response.setDateHeader("Last-Modified", zipFile.lastModified());
                response.setDateHeader("Expires", System.currentTimeMillis() + 1000 * 60 * 60 * 24);
                if (null != request.getHeader("Range")) {
                    response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                    try {
                        // 暂时只处理这2种range格式 1、RANGE: bytes=111- 2、Range: bytes=0-499
                        String numRang = request.getHeader("Range").replaceAll("bytes=", "");
                        String[] strRange = numRang.split("-");
                        if (strRange.length == 2) {
                            pos = Long.parseLong(strRange[0].trim());
                            last = Long.parseLong(strRange[1].trim());
                        } else {
                            pos = Long.parseLong(numRang.replaceAll("-", "").trim());
                        }
                    } catch (NumberFormatException e) {
                        log.error(request.getHeader("Range") + " error");
                        pos = 0;
                    }
                }
                long rangLength = last - pos + 1;
                String contentRange = new StringBuffer("bytes ").append(String.valueOf(pos)).append("-").append(last).append("/").append(String.valueOf(fileSize)).toString();
                response.setHeader("Content-Range", contentRange);
                response.addHeader("Content-Length", Objects.toString(rangLength));
                if (pos > 0) {
                    randomAccessFile.seek(pos);
                }
                byte[] buffer = new byte[1024 * 512];
                //每次以512KB 0.5MB的流量下载
                int length = 0, sendTotal = 0;
                while (sendTotal < rangLength && length != -1) {
                    length = randomAccessFile.read(buffer, 0, ((rangLength - sendTotal) <= buffer.length ?
                            ((int) (rangLength - sendTotal)) : buffer.length));
                    sendTotal = sendTotal + length;
                    os.write(buffer, 0, length);
                }
                Thread.sleep(5000);
                if (os != null) {
                    os.flush();
                }
                if (log.isInfoEnabled()) {
                    log.info(String.format("下载 花费时间 %s(s) ", (System.currentTimeMillis() - downloadStart) / 1000));
                }
            }
        } catch (Exception e) {
            if (StringUtils.endsWithIgnoreCase(e.getMessage(), "Broken pipe")) {
                log.error("用户取消下载");
            }
            log.error(e.getMessage(), e);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (Exception e) {
                }
            }
            if (randomAccessFile != null) {
                try {
                    randomAccessFile.close();
                } catch (Exception e) {
                }
            }

        }
    }

    @GetMapping("/all")
    public void all(ServletRequest req, ServletResponse resp){
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        OutputStream os = null;
        InputStream inputStream = null;
        String downfile = "D:\\BaiduNetdiskDownload\\ownthink_v2.zip";
        File zipFile = null;
        try {
            zipFile = new File(downfile);
            byte[] buffer = new byte[1024 * 512];
            int length=0;
            OutputStream out = response.getOutputStream();
            FileCopyUtils.copy(FileUtils.readFileToByteArray(zipFile), out);
            out.flush();
            out.close();
        } catch (Exception e) {
            log.error(request.getHeader("Range") + " error");
        }
    }

}
